/*
  Copyright (c) 2011, Mikheev Rostislav
  Copyright (c) 2011, FreshFarsh team

  Steel Engine source code is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
/**
  texture.cpp

  @author Mikheev Rostislav <hacenator@gmail.com>
  @date 23.03.2011
  @brief Texture class source code
*/

#include "texture.h"

namespace _STEEL_NAMESPACE {

Texture::Texture() :
  _filter(DEF_FILTER)
{
  // pass
}

Texture::Texture(const char * filename) :
  _filter(DEF_FILTER)
{
  LoadFromFile(filename);
}

Texture::~Texture() {
	if (glIsTexture(_handle))
		glDeleteTextures(1, &_handle);
}

bool Texture::LoadFromFile(const char * filename) {
	ImageLoader loader;

	Image * img = loader.LoadImage(filename);

  // Get image parameters
  _width = img->width();
  _height = img->height();

  // Create OpenGL texture
	if (img->loaded())
    CreateTexture(img);

	return true;
}

bool Texture::CreateTexture(Image * img) {
	_handle = 0;
	glGenTextures(1, &_handle);
	glBindTexture(GL_TEXTURE_2D, _handle);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _filter);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _filter);

	if (img->IsCompressed()) {
		GLsizei mip_width = img->width();
		GLsizei mip_height = img->height();
		int mipmaps = img->mipmaps();

		int offset = 0;
		int block_size = (img->format () == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;

		// Get proc
		//PFNGLCOMPRESSEDTEXIMAGE2D glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2D) wglGetProcAddress("glCompressedTexImage2D");

		// Upload mipmaps to video memory
		for (GLint i = 0; i < mipmaps; i++) {
			GLsizei mip_size = ((mip_width + 3) / 4) * ((mip_height + 3) / 4) * block_size;

			glCompressedTexImage2D(GL_TEXTURE_2D, i, img->format(), mip_width, mip_height, 0, mip_size, img->pixels() + offset);

			mip_width = std::max(mip_width >> 1, 1);
			mip_height = std::max(mip_height >> 1, 1);

			offset += mip_size;
		}
	} else {
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		gluBuild2DMipmaps(GL_TEXTURE_2D, img->channels(), img->width(), img->height(), img->format(), GL_UNSIGNED_BYTE, img->pixels());
//		glTexImage2D(GL_TEXTURE_2D, 0, img->format(), img->width(), img->height(), 0, img->format(), GL_UNSIGNED_BYTE, img->pixels());
	}

	return true;
}

void Texture::Bind() {
	glBindTexture(GL_TEXTURE_2D, _handle);
}

void Texture::Bind(GLenum unit) {
	glActiveTexture(unit);
	glBindTexture(GL_TEXTURE_2D, _handle);
}

}
